package sharemem

import (
	"server_cluster/common/gdconf"
	"server_cluster/common/protoc/pb"
	"sync/atomic"
)

type UserItem struct {
	Normal  [USER_ITEM_NORMAL]Item
	Special [USER_ITEM_SPECIAL]Item
}

type Item struct {
	Id        MyInt32 // 道具id
	Type      int8    // 道具类型
	Num       int32   // 道具数量
	Day       int8    // 道具过期天数
	CdEndTime int64   // 冷却结束时间戳 秒
	EndTime   int64   // 过期时间戳 秒
}

func (i *Item) MemInit() {
	i.Id.NewVal = 0
	i.Id.OldVal = 0
	i.Id.Status = 0
	i.Type = 0
	i.Num = 0
	i.Day = 0
	i.CdEndTime = 0
	i.EndTime = 0
}

func (i *Item) IsUse() bool {
	return i.Id.NewVal != 0 || i.Id.OldVal != 0
}

func (i *Item) IsMe(id int32) bool {
	return i.Id.NewVal == id
}

func (i *Item) GetId() int32 {
	return i.Id.NewVal
}

func (i *Item) IsEmpty() bool {
	return i.Num == 0
}

func (i *Item) IsExpire() bool {
	if i.EndTime == 0 {
		return false
	}
	return MyShm.TimeNow > i.EndTime
}

func (i *Item) SetSync() {
	atomic.AddUint32(&(i.Id.Status), 1)
}

func (i *Item) Clear() {
	i.Id.NewVal = 0
}

func (i *Item) CreateItemNormal(cfg *gdconf.ItemConfig, num int32, day int8, time_now int64) {
	i.Id.NewVal = cfg.ItemId
	i.Type = int8(cfg.Type)
	i.Day = day
	switch cfg.ExTimeType {
	case gdconf.ITEM_EX_TYPE_1:
		i.EndTime = time_now + cfg.ExTime
	case gdconf.ITEM_EX_TYPE_2:
		i.EndTime = cfg.ExTime
	default:
		i.EndTime = 0
	}
	if !cfg.Unique {
		i.Num += num
	} else {
		i.Num = 1
	}
	i.CdEndTime = 0
}

// 须校验道具是否过期
func (i *Item) CheckItemNum(num int32) bool {
	if i.EndTime > 0 && i.EndTime < MyShm.TimeNow {
		return false
	}
	return i.Num >= num
}

func (i *Item) CheckItemCDTime() bool {
	return i.CdEndTime <= MyShm.TimeNow
}

func (i *Item) UpdateItemCDTime(cd_time int64) {
	i.CdEndTime = cd_time
	i.SetSync()
}

func (i *Item) UpdateItemNum(cfg *gdconf.ItemConfig, num int32) {
	if num > 0 && cfg.Unique {
		// 唯一
		return
	}
	i.Num += num
	// 设置数据库同步标识
	i.SetSync()
}

func (i *Item) CreateItemSpecial(cfg *gdconf.ItemConfig, num int32) {
	i.Id.NewVal = cfg.ItemId
	i.Type = int8(cfg.Type)
	if cfg.Unique {
		i.Num = 1
	} else {
		i.Num = num
	}
	i.CdEndTime = 0
	i.Day = 0
	i.EndTime = 0
}

func GetIdByKey(key int32) int32     { return key / ITEM_EXPIRE_RANGE }
func InitItemKeyById(id int32) int32 { return id * ITEM_EXPIRE_RANGE }

func (u *User) GetItemCount(itemId int32) int32 {
	switch itemId {
	case gdconf.ITEM_EXP:
		return 0
	case gdconf.ITEM_GEM:
		return u.Gem.NewVal
	case gdconf.ITEM_GOLD:
		return int32(u.Gold)
	default:
		itemCount := int32(0)
		for _, item := range u.Item.Normal {
			if item.Id.NewVal == itemId {
				itemCount += item.Num
			}
		}
		for _, item := range u.Item.Special {
			if item.Id.NewVal == itemId {
				itemCount += item.Num
			}
		}
		return itemCount
	}
}

func (u *User) GetItemRemainCellNum() int32 {
	num := int32(0)
	for i := 0; i < len(u.Item.Normal); i++ {
		if !u.Item.Normal[i].IsUse() {
			num++
		}
	}
	return num
}
func (u *User) CheckClearItem(Type int8, index int32) {
	switch Type {
	case gdconf.ITEM_TYPE_EQUIP:
	case gdconf.ITEM_TYPE_SPECIAL:
		if u.Item.Special[index].IsEmpty() || u.Item.Special[index].IsExpire() {
			// 清空索引 & 格子
			delete(u.GetItemSpecialMap(), u.Item.Special[index].GetItemKey())
			u.Item.Special[index].Clear()
		}
	default:
		if u.Item.Normal[index].IsEmpty() || u.Item.Normal[index].IsExpire() {
			// 清空索引 & 格子
			delete(u.GetItemNormalMap(), u.Item.Normal[index].GetItemKey())
			u.Item.Normal[index].Clear()
		}
	}
}

func (u *User) PackUserItemAll(rsp *pb.SC_Fetch) {
	rsp.Item = &pb.User_Item{
		Normal:  make([]*pb.Item_Base, 0),
		Special: make([]*pb.Item_Base, 0),
	}
	for k, v := range u.GetItemNormalMap() {
		rsp.Item.Normal = append(rsp.Item.Normal, &pb.Item_Base{
			Cell:      int32(v),
			Id:        GetIdByKey(k),
			Type:      int32(u.Item.Normal[v].Type),
			Num:       u.Item.Normal[v].Num,
			CdEndTime: u.Item.Normal[v].CdEndTime,
			EndTime:   u.Item.Normal[v].EndTime,
		})
		// 道具过期判断
		u.CheckClearItem(u.Item.Normal[v].Type, int32(v))
	}
	for k, v := range u.GetItemSpecialMap() {
		rsp.Item.Special = append(rsp.Item.Special, &pb.Item_Base{
			Cell:      int32(v),
			Id:        GetIdByKey(k),
			Type:      int32(u.Item.Special[v].Type),
			Num:       u.Item.Special[v].Num,
			CdEndTime: u.Item.Special[v].CdEndTime,
			EndTime:   u.Item.Special[v].EndTime,
		})
		u.CheckClearItem(u.Item.Special[v].Type, int32(v))
	}
}
